package cn.shujuhai.qtadmin.platform.pluging.logging;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import cn.shujuhai.qtadmin.platform.domain.SysLogging;

/**
 * Describe: 日 志 切 面 实 现
 * 
 * @author : dch
 */
@Aspect
@Component
public class LoggingAspect {

    private final LoggingFactory loggingFactory;

    public LoggingAspect(LoggingFactory loggingFactory) {
        this.loggingFactory = loggingFactory;
    }

    /**
     * 切 面
     */
    @Pointcut("@annotation(cn.shujuhai.qtadmin.platform.pluging.logging.Logging) || @within(cn.shujuhai.qtadmin.platform.pluging.logging.Logging)")
    public void dsPointCut() {
        // TODO document why this method is empty
    }

    /**
     * 处 理 系 统 日 志
     * 
     * @param joinPoint
     *            joinPoint
     * @return result
     * @throws Throwable
     *             Throwable
     */
    @Around("dsPointCut()")
    private Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        var sysLog = new SysLogging();
        Object result;
        try {
            Logging loggingAnnotation = getLogging(joinPoint);
            sysLog.setTitle(CharSequenceUtil.equals(loggingAnnotation.value(), "暂无标题") ? loggingAnnotation.title()
                : loggingAnnotation.value());
            sysLog.setDescription(loggingAnnotation.describe());
            sysLog.setBusinessType(loggingAnnotation.type());
            sysLog.setSuccess(true);
            sysLog.setRequestParam(JSONUtil.toJsonStr(joinPoint.getArgs()));
            sysLog.setLoggingType(LoggingType.OPERATE);
            result = joinPoint.proceed();
        } catch (Exception exception) {
            sysLog.setSuccess(false);
            sysLog.setErrorMsg(exception.getMessage());
            throw exception;
        } finally {
            loggingFactory.recordLog(sysLog);
        }
        return result;
    }

    /**
     * 获 取 注 解
     * 
     * @param point
     *            point
     * @return return
     */
    public Logging getLogging(@NotNull ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature)point.getSignature();
        Class<?> targetClass = point.getTarget().getClass();
        Logging targetLogging = targetClass.getAnnotation(Logging.class);
        if (targetLogging != null) {
            return targetLogging;
        } else {
            Method method = signature.getMethod();
            return method.getAnnotation(Logging.class);
        }
    }
}
